package com.mageddo.dnsproxyserver.solver.remote.circuitbreaker.application;

import com.mageddo.supporting.circuitbreaker.testing.sandbox.Result;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import testing.templates.circuitbreaker.Resilience4jCircuitBreakerTemplates;

import static com.mageddo.supporting.circuitbreaker.testing.sandbox.resilience4j.Resilience4jCircuitBreakerSandBox.testCircuitOnError;
import static com.mageddo.supporting.circuitbreaker.testing.sandbox.resilience4j.Resilience4jCircuitBreakerSandBox.testCircuitOnSuccess;
import static org.junit.jupiter.api.Assertions.assertEquals;

@Slf4j
public class DpsCircuitBreakerWithManualHalfOpenTest {

  @Test
  void mustNotHalfOpenAutomatically() {

    // arrange
    final var circuit = dpsConfig();
    circuit.transitionToOpenState();

    assertEquals(CircuitBreaker.State.OPEN, circuit.getState());
    testCircuitOnSuccess(Result.CIRCUIT_OPEN, CircuitBreaker.State.OPEN, circuit, 1);

  }

  @Test
  void serverGotUp() {

    // arrange
    final var circuit = dpsConfig();
    circuit.transitionToOpenState();
    circuit.transitionToHalfOpenState();

    // act // assert
    testCircuitOnSuccess(Result.SUCCESS, CircuitBreaker.State.HALF_OPEN, circuit, 8);
    testCircuitOnError(Result.ERROR, CircuitBreaker.State.HALF_OPEN, circuit, 1);
    testCircuitOnError(Result.ERROR, CircuitBreaker.State.CLOSED, circuit, 1);

  }

  @Test
  void serverGoesDownAndDecideToOpenTheCircuitAfterMinimumNumberOfCalls() {

    // arrange
    final var circuit = dpsConfig();

    // act // assert
    testCircuitOnError(Result.ERROR, CircuitBreaker.State.CLOSED, circuit, 4);
    testCircuitOnSuccess(Result.SUCCESS, CircuitBreaker.State.CLOSED, circuit, 1);
    testCircuitOnError(Result.ERROR, CircuitBreaker.State.CLOSED, circuit, 94);
    testCircuitOnSuccess(Result.SUCCESS, CircuitBreaker.State.OPEN, circuit, 1);

  }

  static CircuitBreaker dpsConfig() {
    return Resilience4jCircuitBreakerTemplates.theDefaultHandlingIoException();
  }
}
